home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 August: Tool Chest / Dev.CD Aug 95 TC / Dev.CD Aug 95 TC.toast / New System Software Extensions / QuickDraw™ 3D 1.0 / Samples / SampleCode / Tumbler and Podium / Tumbler_file.c < prev    next >
Encoding:
Text File  |  1995-05-31  |  14.0 KB  |  642 lines  |  [TEXT/MPS ]

  1. //        file.c
  2. //
  3. //        File Input/Output routines.
  4. //        
  5. //
  6. //        Author:        Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team
  7. //        Date:        Thursday, January 26, 1992
  8. //
  9. //    Modification History:
  10. //
  11. //        11/27/94    nick        there seems to be a problem reading metafiles into the app
  12. //        01/25/95    nick        slotted in spin code (thanks kent), updated for viewhints.  
  13. //                                If we have view hints, then we can export things like the 
  14. //                                renderer type and lighting and camera in a drag or cut/copy
  15. //
  16. //
  17. //    To Do:
  18. //         factor for AppleEvents
  19. //
  20. //        Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  21.  
  22. #include "Tumbler_globals.h"
  23. #include "Tumbler_prototypes.h"
  24. #include "Tumbler_resources.h"
  25.  
  26. #include "QD3DStorage.h"
  27. #include "QD3DGroup.h"
  28. #include "QD3DIO.h"
  29. #include "QD3DShader.h"
  30. #include "QD3DView.h"
  31.  
  32. #include "Tumbler_file.h"
  33. #include "Tumbler_camera.h"
  34. #include "Tumbler_document.h"
  35. #include "Tumbler_PICTImport.h"
  36. #include "Tumbler_utility.h"
  37.  
  38.  
  39. #include <string.h>
  40.  
  41. static short  ReadDocumentFile(DocumentPtr theDocument, TQ3Boolean isText);
  42. static PicHandle OpenPICTFile(FSSpec *theFile);
  43. static OSErr WriteDocumentFile(DocumentPtr theDocument);
  44. //-----------------------------------------------------------------------------
  45.  
  46. TQ3Status Tumbler_ReadScene(
  47.     TQ3FileObject        file,
  48.     short                isText,
  49.     TQ3SharedObject        *viewHints,
  50.     TQ3Object            *model)
  51. {
  52.     char                filename[64];
  53. //    TQ3Object            group;
  54.     TQ3Object            object;
  55.     TQ3Boolean            isEOF;
  56.     
  57.     *viewHints    = NULL;
  58.     if( *model ) {
  59.         Q3Object_Dispose(*model);
  60.     }
  61.  
  62.     *model        = Q3DisplayGroup_New();
  63.  
  64. //    group        = NULL;
  65.     object        = NULL;
  66.     
  67.     SetCursor(*GetCursor(watchCursor));
  68.  
  69.     if (Q3File_OpenRead(file, NULL) != kQ3Success)
  70.     {
  71.         SetCursor(&qd.arrow);
  72.         return kQ3Failure;
  73.     }
  74.  
  75.     while ((isEOF = Q3File_IsEndOfFile(file)) == kQ3False)
  76.     {
  77.         object = NULL;
  78.         
  79.         object = Q3File_ReadObject(file);
  80.         
  81.         if (object == NULL) 
  82.         {
  83.             /* 
  84.                 Check and handle errors here - 
  85.                     Some errors may mean more objects are left in the file.
  86.             */
  87.             break;
  88.         }
  89.  
  90.         if (Q3Object_IsType(object, kQ3SharedTypeViewHints))
  91.         {
  92.             if (*viewHints == NULL)
  93.             {
  94.                 *viewHints = object;
  95.                 object = NULL;
  96.             }
  97.         }
  98.         else if (Q3Object_IsDrawable(object))
  99.         {
  100.             if (*model)
  101.             {
  102.                 Q3Group_AddObject(*model, object);
  103.             }
  104. //            else
  105. //            {
  106. //                group = Q3DisplayGroup_New();
  107. //
  108. //                Q3Group_AddObject(group, *model);
  109. //                Q3Group_AddObject(group, object);
  110. //                Q3Object_Dispose(*model);
  111. //
  112. //                *model = group;
  113. //            }
  114.         }
  115.         if (object != NULL) 
  116.             Q3Object_Dispose(object);
  117.     }
  118.             
  119.     Q3File_Close(file);
  120.     
  121.     if (isEOF == kQ3False)
  122.     {
  123.         if (*model != NULL)
  124.         {    Q3Object_Dispose(*model); *model = NULL; }
  125.     
  126.         if (*viewHints != NULL)
  127.         {    Q3Object_Dispose(*viewHints); *viewHints = NULL; }
  128.         
  129.         SetCursor(&qd.arrow);
  130.         return kQ3Failure;
  131.     }
  132.     
  133.     SetCursor(&qd.arrow);
  134.     return kQ3Success;
  135. }
  136.  
  137. //-----------------------------------------------------------------------------
  138. //
  139. //    Tumbler_WriteScene()
  140. //
  141.  
  142. void Tumbler_WriteScene(
  143.     TQ3FileObject        file,
  144.     short                textMode,
  145.     DocumentPtr            theDocument)
  146. {
  147.     TQ3GroupPosition    gPos;
  148.     TQ3Object            object;
  149.     TQ3ViewStatus        fileStatus;
  150.     
  151.     SetCursor(*GetCursor(watchCursor));
  152.  
  153.     if (Q3File_OpenWrite(file, kQ3FileModeText) != kQ3Success)
  154.     {
  155.         SetCursor(&qd.arrow);
  156.         return;
  157.     }
  158.     
  159.     Q3View_StartWriting(theDocument->theView, file);
  160.         
  161.     if (theDocument->viewHints != NULL)
  162.     {
  163.         if (Q3Object_Submit(theDocument->viewHints, theDocument->theView) == kQ3Failure)
  164.         {
  165.             Q3File_Cancel(file);
  166.             SetCursor(&qd.arrow);
  167.             return;
  168.         }
  169.     }
  170.     do {
  171.         if (theDocument->documentGroup != NULL)
  172.         {
  173.                 Q3Group_GetFirstPosition(theDocument->documentGroup, &gPos);
  174.                 while (gPos)
  175.                 {
  176.                     TQ3Status status;
  177.                     
  178.                     Q3Group_GetPositionObject(theDocument->documentGroup, gPos, &object);
  179.                     status = Q3Object_Submit(object, theDocument->theView);
  180.                     Q3Object_Dispose(object);
  181.                     
  182.                     if (status != kQ3Failure)
  183.                     {
  184.                         Q3Group_GetNextPosition(theDocument->documentGroup, &gPos);
  185.                     }
  186.                 }
  187.         }
  188.     } while ((fileStatus = Q3View_EndWriting(theDocument->theView)) == kQ3ViewStatusRetraverse);
  189.         
  190.     if( Q3File_Close(file) == kQ3Failure ) {
  191.         SetCursor(&qd.arrow);
  192.         return;
  193.     }
  194.     SetCursor(&qd.arrow);
  195.     return ;
  196. }
  197.  
  198.  
  199. //-----------------------------------------------------------------------------
  200. // ReadDocumentFile
  201.  
  202. short ReadDocumentFile(DocumentPtr theDocument, TQ3Boolean isText)
  203. {
  204.     TQ3StorageObject        storage;
  205.     TQ3FileObject        fd;
  206.     TQ3Object             objects = nil;
  207.     TQ3Object            viewHints;    
  208.     
  209.     storage = Q3MacintoshStorage_New( theDocument->fRefNum );
  210.     
  211.     if (storage == nil)
  212.         goto bail;
  213.     
  214.     fd = Q3File_New();
  215.     
  216.     if (fd == nil)
  217.         goto bail;
  218.  
  219.     Q3File_SetStorage(fd, storage);
  220.     Q3Object_Dispose(storage);
  221.     
  222.     Tumbler_ReadScene(
  223.         fd,
  224.         isText,
  225.         &viewHints,
  226.         &theDocument->documentGroup) ;
  227.     
  228.     TumblerDocument_UpdateView( theDocument, viewHints ) ;
  229.     
  230.     AdjustLightsPositions(theDocument);
  231.  
  232.     if (viewHints)
  233.         Q3Object_Dispose(viewHints);
  234.  
  235.     Q3Object_Dispose(fd);
  236.  
  237.     return(noErr);
  238. bail:
  239.     Q3Object_Dispose(fd);
  240.  
  241.     return(fnOpnErr);
  242. }
  243.  
  244. //-
  245.  
  246. PicHandle OpenPICTFile(
  247.     FSSpec *theFile)
  248. {
  249.     OSErr        err;
  250.     long        curEOF;
  251.     PicHandle    my_pic;
  252.     long         count;
  253.     Ptr         buffer;
  254.     short        refNum;
  255.     
  256.     if (FSpOpenDF(theFile, fsRdWrPerm, &refNum))
  257.         return(0);
  258.  
  259.     /* get size of file */
  260.     err = GetEOF(refNum, &curEOF);
  261.     if (err != 0) {
  262.         return(0);
  263.     }
  264.     
  265.     /* move the file mark to 512 */
  266.     err = SetFPos(refNum, fsFromStart, 512L);
  267.     if (err != 0) {
  268.         return(0);
  269.     }
  270.  
  271.     /* size of data to read */
  272.     count = curEOF - 512;
  273.     
  274.     /* create the PicHandle */
  275.     my_pic = (PicHandle)NewHandle(count);
  276.     HLock((Handle)my_pic);
  277.     
  278.     /* read the PICT info */
  279.     buffer = (Ptr)(*my_pic);
  280.     err = FSRead(refNum, &count, buffer);
  281.     if (err != 0) {
  282.         return(0);
  283.     }
  284.     HUnlock((Handle)my_pic);
  285.  
  286.     FSClose(refNum);
  287.     
  288.     return (my_pic);
  289. }
  290.  
  291.  
  292.  
  293. OSErr WriteDocumentFile(DocumentPtr theDocument)
  294. {
  295.     OSErr        theResult;
  296.     long        length;
  297.     char        *bufPtr;
  298.  
  299.     SetCursor(*GetCursor(watchCursor));
  300.  
  301.     if (! theDocument->fRefNum)
  302.         return(fnOpnErr);
  303.  
  304.     if ((theResult = SetFPos(theDocument->fRefNum, fsFromStart, 0)) != noErr ) 
  305.         return(theResult);
  306.  
  307.     if( theDocument->documentGroup ) {
  308.         TQ3StorageObject    storage;
  309.         TQ3FileObject    fd;
  310.         
  311.         storage = Q3MacintoshStorage_New(theDocument->fRefNum);
  312.         
  313.         if (storage == nil)
  314.             goto bail;
  315.         
  316.         fd = Q3File_New();
  317.         
  318.         if (fd == nil)
  319.             goto bail;
  320.  
  321.         Q3File_SetStorage(fd, storage);
  322.         Q3Object_Dispose(storage);
  323.         
  324.         Tumbler_WriteScene(fd, 
  325.                             kQ3FileModeText,
  326.                             theDocument) ;
  327.  
  328.         Q3Object_Dispose(fd);
  329.     }
  330.     return(noErr);
  331. bail:
  332.     return(fnOpnErr);
  333. }
  334.  
  335.  
  336. void DoNewDocument(void)
  337.  
  338. {    DocumentPtr theDocument;
  339.  
  340.     if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  341.         ShowWindow(theDocument->theWindow);
  342.     }
  343. }
  344.  
  345. OSErr DoOpenFile(FSSpec *theFile)
  346.  
  347. {    OSErr                result;
  348.     short                refNum;
  349.     DocumentPtr         theDocument;
  350.     FInfo                fndrInfo ;
  351.     TQ3Boolean            isText ;
  352.  
  353.     // we assume the FSSpec passed in was valid, get the file information
  354.     // we need to know the file type, this routine may get called by an appleEvent
  355.     // handler, so we can't assume a type, we need to get it from the fsspec.
  356.     
  357.     FSpGetFInfo( theFile, &fndrInfo ) ;
  358.     
  359.     // pull out the file type
  360.     
  361.     isText = (fndrInfo.fdType == 'TEXT') ;
  362.     
  363.     if ((result = FSpOpenDF(theFile, fsRdWrPerm, &refNum)) != noErr)
  364.         return(result);
  365.  
  366.     if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  367.         theDocument->fRefNum = refNum;
  368.         theDocument->theFileSpec = *theFile ;
  369.         SetCursor(*GetCursor(watchCursor));
  370.         ReadDocumentFile( theDocument, isText ) ;
  371.         SetWTitle(theDocument->theWindow, theFile->name);
  372.         ShowWindow(theDocument->theWindow);
  373.         AdjustCamera(theDocument,
  374.             theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  375.             theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);
  376.         SetCursor(&qd.arrow);
  377.  
  378.     } else {
  379.         SysBeep(1);
  380.         FSClose(refNum);
  381.         return(memFullErr);
  382.     }
  383.     return(noErr);
  384. }
  385.  
  386. void DoImport3DMFDocument(DocumentPtr theDocument)
  387. {
  388.     short                refNum;
  389.     StandardFileReply    theReply;
  390.     SFTypeList            theTypeList = { 'TEXT', '3DMF', nil };
  391.     short                numtypes = 2 ;
  392.  
  393.     if(theDocument == nil)
  394.         return;
  395.  
  396.     StandardGetFile(0L, numtypes, theTypeList, &theReply);
  397.  
  398.     // read for podium files
  399.     if (theReply.sfGood) {
  400.         if(theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') {
  401.  
  402.             // did we try to open a metafile ???
  403.         
  404.             OSErr                result;
  405.             short                refNum;
  406.             DocumentPtr         theDocument;
  407.             FInfo                fndrInfo ;
  408.             TQ3Boolean            isText ;
  409.             
  410.             isText = (theReply.sfType == 'TEXT') ;
  411.             
  412.             if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr)
  413.                 return ;
  414.                 
  415.             theDocument->fRefNum = refNum;
  416.             
  417.             ReadDocumentFile( theDocument, isText ) ;
  418.             
  419. #ifdef PODIUM_APP
  420.             AdjustCamera(theDocument,
  421.                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  422.                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);
  423. #else
  424.         AdjustCamera(theDocument,
  425.             theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  426.             theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);
  427. #endif
  428.  
  429.         } 
  430.     }
  431. }
  432.  
  433.  
  434. //--------------------------------------------------------------------------------
  435. void DoOpenDocument(DocumentPtr theDocument)
  436. {    short                refNum;
  437.  
  438. #ifndef PODIUM_APP
  439.     SFTypeList            theTypeList = { 'TEXT', '3DMF', 'PICT', nil };
  440.     short                numtypes = 3 ;
  441. #else
  442.     SFTypeList            theTypeList = { 'PICT', nil };
  443.     short                numtypes = 1 ;
  444. #endif
  445.  
  446.     StandardFileReply    theReply;
  447.     StandardGetFile(0L, numtypes, theTypeList, &theReply);
  448.  
  449. #ifndef PODIUM_APP
  450.  
  451.     // read for Tumbler files
  452.     if (theReply.sfGood) {
  453.         if( theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') {
  454.             DoOpenFile(&theReply.sfFile);
  455.         } else if( theReply.sfType == 'PICT' && theDocument && theDocument->documentGroup) {
  456.             PicHandle            thePict;
  457.             TQ3StoragePixmap     textureImage;
  458.             
  459.             // get the picture from the file
  460.             thePict = OpenPICTFile(&theReply.sfFile);
  461.             
  462.             // make a texture
  463.             TextureFromPICT( thePict, &textureImage);
  464.             AddTextureToDocument( theDocument, &textureImage);
  465.             
  466.             // and free the space occupied by the picture
  467.             KillPicture(thePict) ;
  468.         
  469.         }
  470.     }
  471. #else
  472.  
  473.     // read for podium files
  474.     if (theReply.sfGood) {
  475.         // podium's slide files are PICT files
  476.         if( theReply.sfType == 'PICT' ) {
  477.  
  478.             short            refNum;
  479.             DocumentPtr        theDocument;
  480.             PicHandle        theBackgroundPict ;
  481.             OSErr            theErr ;
  482.             
  483.             if((theErr = FSpOpenDF(&theReply.sfFile, fsRdPerm, &refNum)) != noErr )
  484.                 return ;
  485.         
  486.             if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  487.                 Rect            bounds;
  488.                 PicHandle        thePict;
  489.                 GWorldPtr        savedGWorld ;
  490.                 GDHandle        savedDevice ;
  491.                 
  492.                 GetGWorld(&savedGWorld,&savedDevice);
  493.                 
  494.                 theBackgroundPict = OpenPICTFile(&theReply.sfFile);
  495.                 bounds = (**theBackgroundPict).picFrame;
  496.  
  497.                 theErr = UpdateGWorld(&theDocument->screenBuffer, 16, &bounds, nil, nil, 0L ) ;
  498.                 if( (theErr = UpdateGWorld(&theDocument->bgOffscreen, 16, &bounds, nil, nil, 0L )) != noErr )  {
  499.                     return ;
  500.                 }
  501.                 
  502.                 // draw the picture into the offscreen    
  503.                 SetGWorld( theDocument->bgOffscreen , nil ) ;
  504.                 DrawPicture( theBackgroundPict, &bounds ) ;
  505.                 SetGWorld(savedGWorld,savedDevice);
  506.                 
  507.                 SizeWindow(theDocument->theWindow, bounds.right - bounds.left, bounds.bottom - bounds.top, false);
  508.                 {
  509.                     Rect    screenRect = (**GetMainDevice()).gdRect;
  510.                     Rect    winRect = theDocument->theWindow->portRect ;
  511.             
  512.                     CenterRectInRect(&screenRect, &winRect) ;
  513.                     MoveWindow(theDocument->theWindow,winRect.left,winRect.top,false);
  514.                 }
  515.                 SetWTitle(theDocument->theWindow, theReply.sfFile.name);
  516.                 ShowWindow(theDocument->theWindow) ;
  517.  
  518.             } else {
  519.             
  520.                 SysBeep(1);
  521.                 FSClose(refNum);
  522.                 return;
  523.                 
  524.             }
  525.         }
  526.         else if(theDocument != nil && (theReply.sfType == 'TEXT' || theReply.sfType == '3DMF')) {
  527.  
  528.             // did we try to open a metafile ???
  529.         
  530.             OSErr                result;
  531.             short                refNum;
  532.             DocumentPtr         theDocument;
  533.             FInfo                fndrInfo ;
  534.             TQ3Boolean            isText ;
  535.             
  536.             isText = (theReply.sfType == 'TEXT') ;
  537.             
  538.             if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr)
  539.                 return ;
  540.                 
  541.             theDocument->fRefNum = refNum;
  542.             
  543.             ReadDocumentFile( theDocument, isText ) ;
  544.             AdjustCamera(theDocument,
  545.                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  546.                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);
  547.         } 
  548.     }
  549. #endif
  550.  
  551. }
  552.  
  553.  
  554. Boolean DoSaveAsDocument(DocumentPtr theDocument)
  555. {    short                theResult;
  556.     Str255                thePrompt, theName;
  557.     StandardFileReply    theReply;
  558.  
  559.     if (! theDocument)
  560.         return(false);
  561.  
  562.     GetIndString(thePrompt, FileStringsID, slSavePromptIndex);
  563.     GetWTitle(theDocument->theWindow, theName);
  564.     StandardPutFile( (ConstStr255Param) &thePrompt, (ConstStr255Param) &theName, &theReply);
  565.  
  566.     if (theReply.sfGood) {
  567.         if (!theReply.sfReplacing) {
  568.             if ((theResult = FSpCreate(&theReply.sfFile, FileCreator, FileType, theReply.sfScript)) != noErr) {
  569.                 SysBeep(1);
  570.                 return(false);
  571.             }
  572.         }
  573.         if (theDocument->fRefNum) {
  574.             theResult = FSClose(theDocument->fRefNum);
  575.         }
  576.         if ((theResult = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &theDocument->fRefNum)) != noErr) {
  577.             SysBeep(1);
  578.             return(false);
  579.         }
  580.  
  581.         if ((theResult = WriteDocumentFile(theDocument)) != noErr) {
  582.             SysBeep(1);
  583.             return(false);
  584.         }
  585.  
  586.         SetWTitle(theDocument->theWindow, theReply.sfFile.name);
  587.         theDocument->dirty = false;
  588.  
  589.     } else {
  590.         return(false);
  591.     }
  592.     return(true);
  593. }
  594.  
  595.  
  596. Boolean DidSaveDocument(DocumentPtr theDocument)
  597. {
  598.  
  599.     if ( theDocument == nil )
  600.         return(false);
  601.  
  602.     if (theDocument->fRefNum) {
  603.         if (WriteDocumentFile(theDocument)) {
  604.             SysBeep(1);
  605.             return(false);
  606.         } else {
  607.             theDocument->dirty = false;
  608.         }
  609.         return(true);
  610.     } else {
  611.         return(DoSaveAsDocument(theDocument));
  612.     }
  613. }
  614.  
  615.  
  616. void DoRevertDocument(DocumentPtr theDocument)
  617.  
  618. {    Str255        theName;
  619.  
  620.     if (! theDocument)
  621.         return;
  622.  
  623.     if (theDocument->fRefNum) {
  624.         GetWTitle(theDocument->theWindow, theName);
  625.         ParamText( (ConstStr255Param) &theName, (ConstStr255Param) "", (ConstStr255Param) "", (ConstStr255Param) "");
  626.         if (Alert(idRevertALRT, 0L) == 1) {
  627.             FInfo                fndrInfo ;
  628.         
  629.             // we assume the FSSpec in the document is valid, get the file information
  630.             // we need to know the file type
  631.             
  632.             FSpGetFInfo( &theDocument->theFileSpec, &fndrInfo ) ;
  633.             
  634.             // pull out the file type
  635.             
  636.             ReadDocumentFile(theDocument, (fndrInfo.fdType == 'TEXT')) ;
  637.         }
  638.     }
  639. }
  640.  
  641.  
  642.